#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.MultiPoint.MultiPointCommonTypes;
using Microsoft.MultiPoint.MultiPointMousePlugIn;
using Microsoft.MultiPoint.MultiPointSDK;
using UTable.Input.MultiTouch;

namespace UTable.Input
{
    public class MultiMouseProvider2 : Grid, IInputProvider, IMultiPointMouseEvents, IMultiPointGenericDeviceEvents
    {
        public Window CurrentWindow
        {
            get
            {
                return MultiMouseProvider2.MultiPointObject.CurrentWindow;
            }
            set
            {
                MultiMouseProvider2.MultiPointObject.RegisterMouseDevice();
                MultiMouseProvider2.MultiPointObject.CurrentWindow = value;
                MultiMouseProvider2.MultiPointObject.DrawMouseDevices();

                // Move system cursor to a fixed location so it doesn't cause any trouble
                MultiPointSDK.SystemCursorPosition = new Point((int)CurrentWindow.Left + 10, (int)CurrentWindow.Top + 10);
                // Hide the system cursor
                MultiPointSDK.HideSystemCursor();

                CursorColorCollection.Clear();
                IDMap.Clear();

                CursorColorCollection.Add(Colors.Green);
                CursorColorCollection.Add(Colors.Red);
                CursorColorCollection.Add(Colors.Yellow);
                CursorColorCollection.Add(Colors.Black);
                CursorColorCollection.Add(Colors.Orange);

                for (int i = 0; i < MultiPointObject.MouseDeviceList.Count; i++)
                {
                    DeviceInfo device_info = (DeviceInfo)(MultiMouseProvider2.MultiPointObject.MouseDeviceList[i]);
                    IDMap.Add(device_info.ID, 0);
                    MouseStateMap.Add(device_info.ID, MouseState.UP);
                    int colorSelector = i % CursorColorCollection.Count;
                    ((MultiPointMouseDevice)device_info.DeviceVisual).CursorColor = CursorColorCollection[colorSelector];
                    ((MultiPointMouseDevice)device_info.DeviceVisual).MouseSpeed = 2;
                    // ((MultiPointMouseDevice)device_info.DeviceVisual).CursorImage = CreateBitmapImage(Properties.Resources.boy_01);
                    ColorMap.Add(device_info.ID, CursorColorCollection[colorSelector]);
                }
                finger_id_count = 0;
                MultiPointObject.DeviceRemoveCompleteEvent += new EventHandler<DeviceNotifyEventArgs>(MultiPointObject_DeviceRemoveCompleteEvent);
                MultiPointObject.DeviceArrivalEvent += new EventHandler<DeviceNotifyEventArgs>(MultiPointObject_DeviceArrivalEvent);
            }
        }

        public static BitmapImage CreateBitmapImage(System.Drawing.Bitmap b)
        {
            BitmapImage bmpimg = new BitmapImage();
            MemoryStream memStream = new MemoryStream();
            bmpimg.BeginInit();
            b.MakeTransparent(System.Drawing.Color.White);
            b.Save(memStream, System.Drawing.Imaging.ImageFormat.Png);
            bmpimg.StreamSource = memStream;
            bmpimg.EndInit();
            return bmpimg;
        }

        void MultiPointObject_DeviceRemoveCompleteEvent(object sender, DeviceNotifyEventArgs e)
        {
            IDMap.Remove(e.DeviceInfo.ID);
            MouseStateMap.Remove(e.DeviceInfo.ID);
            ColorMap.Remove(e.DeviceInfo.ID);
        }

        void MultiPointObject_DeviceArrivalEvent(object sender, DeviceNotifyEventArgs e)
        {
            IDMap.Add(e.DeviceInfo.ID, 0);
            MouseStateMap.Add(e.DeviceInfo.ID, MouseState.UP);
            int colorSelector = this.IDMap.Count % CursorColorCollection.Count;
            ((MultiPointMouseDevice)e.DeviceInfo.DeviceVisual).CursorColor = CursorColorCollection[colorSelector];
            ((MultiPointMouseDevice)e.DeviceInfo.DeviceVisual).MouseSpeed = 2;
            ColorMap.Add(e.DeviceInfo.ID, CursorColorCollection[colorSelector]);
        }

        public MultiMouseProvider2()
        {
            this.Loaded += new RoutedEventHandler(UMultiMouseProvider_Loaded);
            Grid host = new Grid();
            host.Background = new SolidColorBrush(Color.FromArgb(5, 255, 255, 0));
            this.Children.Add(host);
        }

        void UMultiMouseProvider_Loaded(object sender, RoutedEventArgs e)
        {
        }

        static public MultiPointSDK MultiPointObject = MultiPointSDK.GetInstance();


        static MultiMouseProvider2()
        {
            RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseDownEvent, OnMultiPointMouseDownThunk, false);
            RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseUpEvent, OnMultiPointMouseUpThunk, false);

            RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseLeftButtonDownEvent, OnMultiPointMouseLeftButtonDownThunk, false);
            RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseLeftButtonUpEvent, OnMultiPointMouseLeftButtonUpThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseRightButtonDownEvent, OnMultiPointMouseRightButtonDownThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseRightButtonUpEvent, OnMultiPointMouseRightButtonUpThunk, false);

            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseDownEvent, OnMultiPointPreviewMouseDownThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseUpEvent, OnMultiPointPreviewMouseUpThunk, false);

            //RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseEnterEvent, OnMultiPointMouseEnterThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseLeaveEvent, OnMultiPointMouseLeaveThunk, false);
            RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseMoveEvent, OnMultiPointMouseMoveThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointMouseWheelEvent, OnMultiPointMouseWheelThunk, false);

            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseLeftButtonDownEvent, OnMultiPointPreviewMouseLeftButtonDownThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseLeftButtonUpEvent, OnMultiPointPreviewMouseLeftButtonUpThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseRightButtonDownEvent, OnMultiPointPreviewMouseRightButtonDownThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseRightButtonUpEvent, OnMultiPointPreviewMouseRightButtonUpThunk, false);

            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseMoveEvent, OnMultiPointPreviewMouseMoveThunk, false);
            //RegisterClassHandler(MultiPointMouseEvents.MultiPointPreviewMouseWheelEvent, OnMultiPointPreviewMouseWheelThunk, false);

            ////Generic Events
            //RegisterClassHandler(MultiPointGenericDeviceEvents.MultiPointDeviceDownEvent, OnMultiPointDeviceDownThunk, false);
            //RegisterClassHandler(MultiPointGenericDeviceEvents.MultiPointDeviceUpEvent, OnMultiPointDeviceUpThunk, false);
            //RegisterClassHandler(MultiPointGenericDeviceEvents.MultiPointDeviceMoveEvent, OnMultiPointDeviceMoveThunk, false);
        }



        /// <summary>
        /// This method will register a MultiPoint event and its corresponding handler
        /// with the EventManager of WPF event system.
        /// </summary>
        /// <param name="routedEvent">MultiPoint Event</param>
        /// <param name="handler">Handler for the MultiPoint Event</param>
        /// <param name="handledEventsToo">Determines whether the handled events should be re-raised or not</param>
        private static void RegisterClassHandler(RoutedEvent routedEvent, RoutedEventHandler handler, bool handledEventsToo)
        {
            EventManager.RegisterClassHandler(typeof(MultiMouseProvider2), routedEvent, handler, handledEventsToo);
        }


        #region RoutedEventHandler

        #region MouseDown and MouseUp

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseDown event
        /// </summary>
        public event RoutedEventHandler MultiPointMouseDownEvent
        {
            add
            {
                // MultiPointMouseEvents.AddMultiPointMouseDownHandler(this, value);
                this.AddHandler(MultiPointMouseEvents.MultiPointPreviewMouseDownEvent, value);
            }

            remove
            {
                // MultiPointMouseEvents.RemoveMultiPointMouseDownHandler(this, value);
                this.RemoveHandler(MultiPointMouseEvents.MultiPointMouseDownEvent, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseUp event
        /// </summary>
        public event RoutedEventHandler MultiPointMouseUpEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseUpHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseUpHandler(this, value);
            }
        }

        #endregion

        #region LeftButtonDown and LeftButtonUp

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseLeftButtonDownEvent event
        /// </summary>
        public event RoutedEventHandler MultiPointMouseLeftButtonDownEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseLeftButtonDownHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseLeftButtonDownHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseLeftButtonUpEvent event
        /// </summary>
        public event RoutedEventHandler MultiPointMouseLeftButtonUpEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseLeftButtonUpHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseLeftButtonUpHandler(this, value);
            }
        }

        #endregion

        #region RightButtonDown and RightButtonUp

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseRightButtonDownEvent event
        /// </summary>        
        public event RoutedEventHandler MultiPointMouseRightButtonDownEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseRightButtonDownHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseRightButtonDownHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseRightButtonUpEvent event
        /// </summary>   
        public event RoutedEventHandler MultiPointMouseRightButtonUpEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseRightButtonUpHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseRightButtonUpHandler(this, value);
            }
        }

        #endregion

        #region MouseMove and MouseWheel
        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseMoveEvent event
        /// </summary> 
        public event RoutedEventHandler MultiPointMouseMoveEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseMoveHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseMoveHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseWheelEvent event
        /// </summary> 
        public event RoutedEventHandler MultiPointMouseWheelEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseWheelHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseWheelHandler(this, value);
            }
        }

        #endregion

        #region MouseEnter and MouseLeave

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseEnterEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointMouseEnterEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseEnterHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseEnterHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointMouseLeaveEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointMouseLeaveEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointMouseLeaveHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointMouseLeaveHandler(this, value);
            }
        }

        #endregion

        #region Device Events

        /// <summary>
        /// Add or remove an event-handler for MultiPointDeviceDown event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointDeviceDown
        {
            add
            {
                MultiPointGenericDeviceEvents.AddDeviceDownHandler(this, value);
            }

            remove
            {
                MultiPointGenericDeviceEvents.RemoveDeviceDownHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointDeviceUp event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointDeviceUp
        {
            add
            {
                MultiPointGenericDeviceEvents.AddDeviceUpHandler(this, value);
            }

            remove
            {
                MultiPointGenericDeviceEvents.RemoveDeviceUpHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointDeviceMove event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointDeviceMove
        {
            add
            {
                MultiPointGenericDeviceEvents.AddDeviceMoveHandler(this, value);
            }

            remove
            {
                MultiPointGenericDeviceEvents.RemoveDeviceMoveHandler(this, value);
            }
        }

        #endregion

        #region PreviewMouseDown and PreviewMouseUp

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseDownEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseDownEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseDownHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseDownHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseUpEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseUpEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseUpHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseUpHandler(this, value);
            }
        }

        #endregion

        #region PreviewLeftButtonDown and PreviewLeftButtonUp

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseLeftButtonDownEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseLeftButtonDownEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseLeftButtonDownHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseLeftButtonDownHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseLeftButtonUpEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseLeftButtonUpEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseLeftButtonUpHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseLeftButtonUpHandler(this, value);
            }
        }

        #endregion

        #region PreviewRightButtonDown and PreviewRightButtonUp

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseRightButtonDownEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseRightButtonDownEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseRightButtonDownHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseRightButtonDownHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseRightButtonUpEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseRightButtonUpEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseRightButtonUpHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseRightButtonUpHandler(this, value);
            }
        }

        #endregion

        #region PreviewMouseMove and PreviewMouseWheel

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseMoveEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseMoveEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseMoveHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseMoveHandler(this, value);
            }
        }

        /// <summary>
        /// Add or remove an event-handler for MultiPointPreviewMouseWheelEvent event on the MultiPoint CheckBox.
        /// </summary> 
        public event RoutedEventHandler MultiPointPreviewMouseWheelEvent
        {
            add
            {
                MultiPointMouseEvents.AddMultiPointPreviewMouseWheelHandler(this, value);
            }

            remove
            {
                MultiPointMouseEvents.RemoveMultiPointPreviewMouseWheelHandler(this, value);
            }
        }

        #endregion

        #endregion RoutedEventHandlers


        #region Thunk Events Handler
        #region MouseDownThunk and MouseUpThunk

        /// <summary>
        /// The method is an event handler for MultiPointMouseDown event, 
        /// which in turn calls the OnMultiPointMouseButtonDown method. 
        /// </summary>
        /// <param name="sender">MultiPoint Control</param>
        /// <param name="e">Event Data</param>
        private static void OnMultiPointMouseDownThunk(object sender, RoutedEventArgs e)
        {
            MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
            if (eventThunk != null)
            {
                eventThunk.OnMultiPointMouseDown(sender, e);

                MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
                if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_LEFT_BUTTON_DOWN)
                {
                    args.RoutedEvent = MultiPointMouseEvents.MultiPointMouseLeftButtonDownEvent;
                    args.Source = sender;
                    ((UIElement)args.Source).RaiseEvent(args);
                }
                else if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_RIGHT_BUTTON_DOWN)
                {
                    args.RoutedEvent = MultiPointMouseEvents.MultiPointMouseRightButtonDownEvent;
                    args.Source = sender;
                    ((UIElement)args.Source).RaiseEvent(args);
                }
            }
        }

        /// <summary>
        /// The method is an event handler for MultiPointMouseUp event
        /// which in turn calls the OnMultiPointMouseUp method. 
        /// </summary>
        /// <param name="sender">MultiPoint Control</param>
        /// <param name="e">Event Data</param>
        private static void OnMultiPointMouseUpThunk(object sender, RoutedEventArgs e)
        {
            MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
            if (eventThunk != null)
            {
                eventThunk.OnMultiPointMouseUp(sender, e);

                MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
                if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_LEFT_BUTTON_UP)
                {
                    args.RoutedEvent = MultiPointMouseEvents.MultiPointMouseLeftButtonUpEvent;
                    args.Source = sender;
                    ((UIElement)args.Source).RaiseEvent(args);
                }
                else if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_RIGHT_BUTTON_UP)
                {
                    args.RoutedEvent = MultiPointMouseEvents.MultiPointMouseRightButtonUpEvent;
                    args.Source = sender;
                    ((UIElement)args.Source).RaiseEvent(args);
                }
            }
        }

        #endregion

        #region LeftButtonDownThunk and LeftButtonUpThunk

        /// <summary>
        /// The method is an event handler for MultiPointMouseLeftButtonDown event
        /// which in turn calls the OnMultiPointMouseLeftButtonDown method. 
        /// </summary>
        /// <param name="sender">MultiPoint Control</param>
        /// <param name="e">Event Data</param>
        private static void OnMultiPointMouseLeftButtonDownThunk(object sender, RoutedEventArgs e)
        {
            MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
            if (eventThunk != null)
            {
                eventThunk.OnMultiPointMouseLeftButtonDown(sender, e);
            }
        }

        /// <summary>
        /// The method is an event handler for MultiPointMouseLeftButtonUp event 
        /// which in turn calls the OnMultiPointMouseLeftButtonUp method. 
        /// </summary>
        /// <param name="sender">MultiPoint Control</param>
        /// <param name="e">Event Data</param>
        private static void OnMultiPointMouseLeftButtonUpThunk(object sender, RoutedEventArgs e)
        {
            MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
            if (eventThunk != null)
            {
                eventThunk.OnMultiPointMouseLeftButtonUp(sender, e);
            }
        }

        #endregion

        /*
		#region RightButtonDownThunk and RightButtonUpThunk

		/// <summary>
		/// The method is an event handler for MultiPointMouseRightButtonDown event
		/// which in turn calls the OnMultiPointMouseRightButtonDown method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointMouseRightButtonDownThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointMouseRightButtonDown(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for MultiPointMouseRightButtonUp event
		/// which in turn calls the OnMultiPointMouseRightButtonUp method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointMouseRightButtonUpThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointMouseRightButtonUp(sender, e);
			}
		}

		#endregion*/


        #region MouseMoveThunk and MouseWheelThunk

        /// <summary>
        /// The method is an event handler for MultiPointMouseMove event
        /// which in turn calls the OnMultiPointMouseMove method. 
        /// </summary>
        /// <param name="sender">MultiPoint Control</param>
        /// <param name="e">Event Data</param>
        private static void OnMultiPointMouseMoveThunk(object sender, RoutedEventArgs e)
        {
            MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
            if (eventThunk != null)
            {
                eventThunk.OnMultiPointMouseMove(sender, e);
            }
        }

        /// <summary>
        /// The method is an event handler for MultiPointMouseWheel event
        /// which in turn calls the OnMultiPointMouseWheel method. 
        /// </summary>
        /// <param name="sender">MultiPoint Control</param>
        /// <param name="e">Event Data</param>
        private static void OnMultiPointMouseWheelThunk(object sender, RoutedEventArgs e)
        {
            MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
            if (eventThunk != null)
            {
                eventThunk.OnMultiPointMouseWheel(sender, e);
            }
        }

        #endregion

		#region MouseEnterThunk and MouseLeaveThunk

		/// <summary>
		/// The method is an event handler for MultiPointMouseEnter event
		/// which in turn calls the OnMultiPointMouseEnter method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointMouseEnterThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointMouseEnter(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for MultiPointMouseLeave event
		/// which in turn calls the OnMultiPointMouseLeave method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointMouseLeaveThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointMouseLeave(sender, e);
			}
		}

		#endregion

		#region Device Events

		/// <summary>
		/// The method is an event handler for OnMultiPointDeviceDownThunk event
		/// which in turn calls the OnMultiPointDeviceDown method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointDeviceDownThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointDeviceDown(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for OnMultiPointDeviceUpThunk event
		/// which in turn calls the OnMultiPointDeviceUp method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointDeviceUpThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointDeviceUp(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for OnMultiPointDeviceMoveThunk event
		/// which in turn calls the OnMultiPointDeviceMove method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointDeviceMoveThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointDeviceMove(sender, e);
			}
		}

		#endregion

		#region PreviewMouseDownThunk and PreviewMouseUpThunk

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseDown event
		/// which in turn calls the OnMultiPointPreviewMouseButtonDown method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseDownThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseDown(sender, e);

				MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
				if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_LEFT_BUTTON_DOWN)
				{
					args.RoutedEvent = MultiPointMouseEvents.MultiPointPreviewMouseLeftButtonDownEvent;
					args.Source = sender;
					((UIElement)args.Source).RaiseEvent(args);
				}
				else if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_RIGHT_BUTTON_DOWN)
				{
					args.RoutedEvent = MultiPointMouseEvents.MultiPointPreviewMouseRightButtonDownEvent;
					args.Source = sender;
					((UIElement)args.Source).RaiseEvent(args);
				}
			}
		}

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseUp event
		/// which in turn calls the OnMultiPointPreviewMouseUp method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseUpThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseUp(sender, e);

				MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
				if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_LEFT_BUTTON_UP)
				{
					args.RoutedEvent = MultiPointMouseEvents.MultiPointPreviewMouseLeftButtonUpEvent;
					args.Source = sender;
					((UIElement)args.Source).RaiseEvent(args);
				}
				else if (args.RawMouseInfo.UlButtonFlags == MouseWin32Constants.RI_MOUSE_RIGHT_BUTTON_UP)
				{
					args.RoutedEvent = MultiPointMouseEvents.MultiPointPreviewMouseRightButtonUpEvent;
					args.Source = sender;
					((UIElement)args.Source).RaiseEvent(args);
				}
			}
		}

		#endregion

		#region PreviewleftButtonDownThunk and PreviewLeftButtonUpThunk

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseLeftButtonDown event
		/// which in turn calls the OnMultiPointPreviewMouseLeftButtonDown method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseLeftButtonDownThunk(object sender, RoutedEventArgs e)
		{

			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseLeftButtonDown(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseLeftButtonUp event
		/// which in turn calls the OnMultiPointPreviewMouseLeftButtonUp method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseLeftButtonUpThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseLeftButtonUp(sender, e);
			}
		}

		#endregion

		#region PreviewRightButtonDownThunk and PreviewRightButtonUpThunk

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseRightButtonDown event
		/// which in turn calls the OnMultiPointPreviewMouseRightButtonDown method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseRightButtonDownThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseRightButtonDown(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseRightButtonUp event, 
		/// which then delegates the call to control抯 IMultiPointMouseEventThunk.OnMultiPointPreviewMouseRightButtonUpThunk event, 
		/// which in turn calls the adapter抯 OnMultiPointPreviewMouseRightButtonUp method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseRightButtonUpThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseRightButtonUp(sender, e);
			}
		}

		#endregion

		#region PreviewMouseMoveThunk and PreviewMouseWheelThunk

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseMove event
		/// which in turn calls the OnMultiPointPreviewMouseMove method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseMoveThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseMove(sender, e);
			}
		}

		/// <summary>
		/// The method is an event handler for MultiPointPreviewMouseWheel event
		/// which in turn calls the OnMultiPointPreviewMouseWheel method. 
		/// </summary>
		/// <param name="sender">MultiPoint Control</param>
		/// <param name="e">Event Data</param>
		private static void OnMultiPointPreviewMouseWheelThunk(object sender, RoutedEventArgs e)
		{
			MultiMouseProvider2 eventThunk = sender as MultiMouseProvider2;
			if (eventThunk != null)
			{
				eventThunk.OnMultiPointPreviewMouseWheel(sender, e);
			}
		}

		#endregion* /


        #endregion


        #region Events Process

        Dictionary<int, int> IDMap = new Dictionary<int, int>();
        Collection<Color> CursorColorCollection = new Collection<Color>();
        Dictionary<int, Color> ColorMap = new Dictionary<int, Color>();
        Dictionary<int, MouseState> MouseStateMap = new Dictionary<int, MouseState>();

        public Color ActiveColor = Colors.Pink;

        enum MouseState
        {
            DOWN,
            UP
        }

        /// <summary>
        /// This method is called by MultiPointMouseDown Event handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseDown(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointMouseUp handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseUp(object sender, RoutedEventArgs e)
        {
        }

        int finger_id_count = 0;

        /// <summary>
        ///  This method is called by MultiPointMouseLeftButtonDown Event Handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseLeftButtonDown(object sender, RoutedEventArgs e)
        {
            finger_id_count++;
            MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
            int device_id = args.DeviceInfo.ID;
            FingerEventArgs finger_event = new FingerEventArgs();
            finger_event.Timestamp = InputEventArgs.GetTimestamp();
            finger_event.DeviceName = this.GetType().ToString();
            finger_event.UserID = device_id + 1;
            finger_event.FingerID = finger_id_count;
            IDMap[device_id] = finger_id_count;
            finger_event.EventType = FingerEventType.FINGER_DOWN_EVENT;
            Point p = ((MultiPointMouseDevice)(args.DeviceInfo).DeviceVisual).GetPosition();
            p = this.PointFromScreen(p);
            finger_event.Position = CurrentWindow.TranslatePoint(p, this);
			finger_event.GlobalPosition = finger_event.Position;
            Collection<FingerEventArgs> event_colection = new Collection<FingerEventArgs>();
            event_colection.Add(finger_event);
            MultiTouchEventArgs multitouch_event = new MultiTouchEventArgs(event_colection, InputEventArgs.GetTimestamp());
            if (InputTriggered != null)
                InputTriggered(multitouch_event);
            MouseStateMap[device_id] = MouseState.DOWN;

            // set down color
            ((MultiPointMouseDevice)(args.DeviceInfo).DeviceVisual).CursorColor = ActiveColor;
            e.Handled = true;
        }

        /// <summary>
        /// This method is called by MultiPointMouseLeftButtonUp handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
            int device_id = args.DeviceInfo.ID;
            FingerEventArgs finger_event = new FingerEventArgs();
            finger_event.Timestamp = InputEventArgs.GetTimestamp();
            finger_event.DeviceName = this.GetType().ToString();
            finger_event.UserID = device_id + 1;
            finger_event.FingerID = IDMap[device_id];
            finger_event.EventType = FingerEventType.FINGER_UP_EVENT;
            Point p = ((MultiPointMouseDevice)(args.DeviceInfo).DeviceVisual).GetPosition();
            p = this.PointFromScreen(p);
            finger_event.Position = CurrentWindow.TranslatePoint(p, this);
			finger_event.GlobalPosition = finger_event.Position;
            Collection<FingerEventArgs> event_colection = new Collection<FingerEventArgs>();
            event_colection.Add(finger_event);
            MultiTouchEventArgs multitouch_event = new MultiTouchEventArgs(event_colection, InputEventArgs.GetTimestamp());
            if (InputTriggered != null)
                InputTriggered(multitouch_event);
            MouseStateMap[device_id] = MouseState.UP;

            ((MultiPointMouseDevice)(args.DeviceInfo).DeviceVisual).CursorColor = ColorMap[device_id];
            e.Handled = true;
        }

        /// <summary>
        /// This method is called by MultiPointMouseRightButtonDown handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseRightButtonDown(object sender, RoutedEventArgs e)
        {
        }


        /// <summary>
        /// This method is called by MultiPointMouseRightbuttonUp Event handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseRightButtonUp(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointMouseEnter handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseEnter(object sender, RoutedEventArgs e)
        {
            MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
        }

        /// <summary>
        /// This method is called by MultiPointMouseLeave handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseLeave(object sender, RoutedEventArgs e)
        {
            MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
        }

        /// <summary>
        /// This method is called by MultiPointMouseMove handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseMove(object sender, RoutedEventArgs e)
        {
            MultiPointMouseEventArgs args = (MultiPointMouseEventArgs)e;
            int device_id = args.DeviceInfo.ID;
            if (MouseStateMap[device_id] == MouseState.UP)
                return;
            FingerEventArgs finger_event = new FingerEventArgs();
            finger_event.Timestamp = InputEventArgs.GetTimestamp();
            finger_event.DeviceName = this.GetType().ToString();
            finger_event.UserID = device_id + 1;
            finger_event.FingerID = IDMap[device_id];
            finger_event.EventType = FingerEventType.FINGER_MOVE_EVENT;
            Point p = ((MultiPointMouseDevice)(args.DeviceInfo).DeviceVisual).GetPosition();
            p = this.PointFromScreen(p);
            finger_event.Position = CurrentWindow.TranslatePoint(p, this);
			finger_event.GlobalPosition = finger_event.Position;
            Collection<FingerEventArgs> event_colection = new Collection<FingerEventArgs>();
            event_colection.Add(finger_event);
            MultiTouchEventArgs multitouch_event = new MultiTouchEventArgs(event_colection, InputEventArgs.GetTimestamp());
            InputTriggered(multitouch_event);
            e.Handled = true;
        }

        /// <summary>
        /// This method is called by MultiPointDeviceDown handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointDeviceDown(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointDeviceUp handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointDeviceUp(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointdeviceMove handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointDeviceMove(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointMouseWheel handler
        /// </summary>
        /// <param name="sender">MultiPointChcekBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointMouseWheel(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseDown handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseDown(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseUp handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseUp(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseLeftButtonDown handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseLeftButtonUp handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseRightButtonDown handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseRightButtonDown(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseRightButtonUp handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseRightButtonUp(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseMove handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseMove(object sender, RoutedEventArgs e)
        {
        }

        /// <summary>
        /// This method is called by MultiPointPreviewMouseWheel handler
        /// </summary>
        /// <param name="sender">MultiPointCheckBox</param>
        /// <param name="e">RoutedEvent Data</param>
        protected virtual void OnMultiPointPreviewMouseWheel(object sender, RoutedEventArgs e)
        {
        }

        #endregion


        #region IInputProvider Members

        public event InputEventHandler InputTriggered;

        public void Initialize(UTable.Objects.UApplication context)
        {
            this.CurrentWindow = context.MainWindow;
            context.Host.Children.Add(this);
        }

        #endregion
    }
}
